package com.gzsxy.esjy.service.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gzsxy.esjy.common.base.exception.impl.CustomAssert;
import com.gzsxy.esjy.common.base.result.ResultCodeEnum;
import com.gzsxy.esjy.redis.user.ISystemUser;
import com.gzsxy.esjy.service.base.dto.request.ProductAttributeRequest;
import com.gzsxy.esjy.service.base.dto.request.ProductPicRequest;
import com.gzsxy.esjy.service.base.dto.request.ProductRequest;
import com.gzsxy.esjy.service.base.dto.response.*;
import com.gzsxy.esjy.service.base.DictionaryConstants;
import com.gzsxy.esjy.service.product.dao.*;
import com.gzsxy.esjy.service.product.entity.Product;
import com.gzsxy.esjy.service.product.entity.ProductAttribute;
import com.gzsxy.esjy.service.product.entity.ProductPic;
import com.gzsxy.esjy.service.product.entity.Verify;
import com.gzsxy.esjy.service.product.entity.vo.ApiProductQueryVo;
import com.gzsxy.esjy.service.product.entity.vo.CommentQueryVo;
import com.gzsxy.esjy.service.product.entity.vo.ProductQueryVo;
import com.gzsxy.esjy.service.product.service.ProductAttributeService;
import com.gzsxy.esjy.service.product.service.ProductPicService;
import com.gzsxy.esjy.service.product.service.ProductService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @author xiaolong
 * @version 1.0
 * @description: 商品
 * @date 2022/1/10 22:35
 */
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {

    @Autowired
    private ProductMapper productMapper;


    @Autowired
    private ISystemUser  iSystemUser;

    @Autowired
    private ProductAttributeService productAttributeService;

    @Autowired
    private ProductPicService productPicService;

    @Autowired
    private ProductPicMapper productPicMapper;

    @Autowired
    private VerifyMappper verifyMappper;

    @Autowired
    private ProductAttributeMapper productAttributeMapper;

    @Autowired
    private CommentMapper commentMapper;

    /**
     * @description: 分页查询
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public PageResult<ProductRsp> selectPage(IPage<Product> pageParam, ProductQueryVo productQueryVo) {

        String title = productQueryVo.getTitle();
        String productCode = productQueryVo.getProductCode();
        String id = productQueryVo.getId();
        Integer publishStatus = productQueryVo.getPublishStatus();
        String joinDateBegin = productQueryVo.getJoinDateBegin();
        Integer verifyStatus = productQueryVo.getVerifyStatus();
        String categoryId = productQueryVo.getCategoryId();
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(title)){
            wrapper.like("p.title",title);
        }
        if (StringUtils.isNotEmpty(productCode)){
            wrapper.eq("p.product_code",productCode);
        }
        if (StringUtils.isNotEmpty(id)){
            wrapper.eq("p.id",id);
        }
        if (publishStatus != null){
            wrapper.eq("p.publish_status",publishStatus);
        }
        //时间大于等于
        if (StringUtils.isNotEmpty(joinDateBegin)){
            wrapper.ge("p.create_time",joinDateBegin);
        }
        if (verifyStatus != null){
            wrapper.eq("p.verify_status",verifyStatus);
        }
        if (categoryId != null){
            wrapper.eq("p.category_id",categoryId);
        }
        wrapper.orderByDesc("p.create_time");
        wrapper.orderByDesc("p.marker");
        wrapper.eq("p.is_deleted",DictionaryConstants.NUMBER_0);
        //判断当前用户是否为系统管理员（默认查询全部商品）
        Boolean isAdmin = (Boolean) iSystemUser.get("isAdmin", true);
        if (!isAdmin){
            String userId = (String) iSystemUser.get("id", "");
            wrapper.eq("p.user_id",userId);
        }
        PageResult<ProductRsp> pageResult = new PageResult<>();
        //分页查询
        if (pageParam != null){
            IPage<ProductRsp> rsp = productMapper.selectPageByProductQueryVo(pageParam, wrapper);
            List<ProductRsp> productRsps = rsp.getRecords();
            //将商品的分类列表按照分类层级升序排列
            productRsps.stream().map(productRsp -> productRsp.getCategoryList().stream().sorted(Comparator.comparing(CategoryRsp::getCategoryLevel)).collect(Collectors.toList()));
            //把审核状态成功的记录放在列表第一个
            productRsps.stream().map(productRsp -> productRsp.getVerifyList().stream().sorted(Comparator.comparing(VerifyRsp::getVerifyStatus)));
            pageResult.setRecords(productRsps);
            pageResult.setTotal(rsp.getTotal());
            //条件查询
        } else {
            List<Product> products = productMapper.selectList1(wrapper);
            List<ProductRsp> productRsps = JSON.parseArray(JSON.toJSONString(products), ProductRsp.class);
            pageResult.setRecords(productRsps);
        }
        return pageResult;
    }


    /**
     * @description: 添加商品
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addProduct(ProductRequest productRequest) {
        Product product = new Product();
        productRequest.setProductCode(String.valueOf(System.currentTimeMillis()));
        BeanUtils.copyProperties(productRequest,product);
        product.setPublishStatus(DictionaryConstants.NUMBER_0);
        product.setVerifyStatus(DictionaryConstants.NUMBER_0);
        String userId = (String) iSystemUser.get("id", "");
        product.setUserId(userId);
        productMapper.insert(product);
        //TODO  添加商品参数
        List<ProductAttributeRequest> productAttr = productRequest.getProductAttr();
        List<ProductAttribute> productAttributes = JSON.parseArray(JSON.toJSONString(productAttr), ProductAttribute.class);
        //mybatisplus会回填一个id
        List<ProductAttribute> list = productAttributes.stream().map(productAttribute -> productAttribute.setProductId(product.getId())).collect(Collectors.toList());
        //批量保存
        productAttributeService.saveBatch(list);

        //TODO 添加商品图片
        List<ProductPicRequest> productPic = productRequest.getProductPic();
        List<ProductPic> productPics = JSON.parseArray(JSON.toJSONString(productPic), ProductPic.class);
        List<ProductPic> pics = productPics.stream().map(productPic1 -> productPic1.setProductId(product.getId())).collect(Collectors.toList());
        productPicService.saveBatch(pics);

        //TODO 添加商品审核
        Verify verify = new Verify();
        verify.setProductId(product.getId());
        //默认未审核
        verify.setVerifyStatus(DictionaryConstants.NUMBER_0);
        verifyMappper.insert(verify);


    }


    /**
     * @description: 更新商品
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateProduct(ProductRequest productRequest) {

        Product product = productMapper.selectById(productRequest.getId());
        //商品不存在
        CustomAssert.notTrue(ObjectUtils.isNotEmpty(product), ResultCodeEnum.PRODUCT_NOT_EXIST_ERROR.getMessage());
        Product product1 = new Product();
        BeanUtils.copyProperties(productRequest,product1);
        productMapper.updateById(product1);

        //TODO 更新商品图片
        List<ProductPicRequest> productPic = productRequest.getProductPic();
        List<ProductPic> productPics = JSON.parseArray(JSON.toJSONString(productPic), ProductPic.class);
        List<ProductPic> pics = productPics.stream().map(productPic1 -> productPic1.setProductId(productRequest.getId())).collect(Collectors.toList());
        //获取商品下的所有图片
        List<ProductPicRsp> productPicRsps = productPicService.getPicByProductId(productRequest.getId());
        Map<String, ProductPicRsp> productPicMap = productPicRsps.stream().collect(Collectors.toMap(ProductPicRsp::getId, o -> o));
        //2.第二种方式（性能提高）
        List<ProductPic> addList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(pics)){
            for (ProductPic productPicRequest : pics) {
                //如果原商品图片存在传入的图片
                if (productPicMap.containsKey(productPicRequest.getId())){
                    //删除map对象中存在的元素
                    productPicMap.remove(productPicRequest.getId());
                } else {
                    addList.add(productPicRequest);
                }
            }
        }
        List<String> deleteIdList = productPicMap.values().stream().map(ProductPicRsp::getId).collect(Collectors.toList());
        //批量删除
        if (CollectionUtils.isNotEmpty(deleteIdList)){
            productPicMapper.deleteBatchIds(deleteIdList);
        }
        //批量添加
        if (CollectionUtils.isNotEmpty(addList)){
            productPicService.saveBatch(addList);
        }
        //TODO 更新商品属性参数
        List<ProductAttributeRequest> productAttr = productRequest.getProductAttr();
        //如果数据库存在该商品参数，则将最新的参数值修改更新；否则添加
        productAttr.stream().map(attr ->{
            LambdaQueryWrapper<ProductAttribute> wrapper = Wrappers.lambdaQuery();
            wrapper.eq(ProductAttribute::getAttrId,attr.getAttrId());
            wrapper.eq(ProductAttribute::getProductId,productRequest.getId());
            ProductAttribute productAttribute = productAttributeMapper.selectOne(wrapper);
            if (com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isNotEmpty(productAttribute)){
                //如果参数值未更新，则无需更新数据库
                if (!productAttribute.getAttrVals().equals(attr.getAttrVals())){
                    productAttribute.setAttrVals(attr.getAttrVals());
                    productAttributeMapper.updateById(productAttribute);
                }
            } else {
                ProductAttribute attribute = new ProductAttribute();
                BeanUtils.copyProperties(attr,attribute);
                attribute.setProductId(productRequest.getId());
                productAttributeMapper.insert(attribute);
            }
            return attr;
        }).collect(Collectors.toList());
//        List<ProductAttribute> productAttributes = JSON.parseArray(JSON.toJSONString(productAttr), ProductAttribute.class);
//        //mybatisplus会回填一个id
//        List<ProductAttribute> list = productAttributes.stream().map(productAttribute -> productAttribute.setProductId(productRequest.getId())).collect(Collectors.toList());
//        //批量保存
//        productAttributeService.saveBatch(list);


    }


    /**
     * @description: 删除商品
     * @param id 商品id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteProduct(String id) {
        Product product = productMapper.selectById(id);
        //商品不存在
        CustomAssert.notTrue(ObjectUtils.isNotEmpty(product),ResultCodeEnum.PRODUCT_NOT_EXIST_ERROR.getMessage());
        productMapper.deleteById(id);

        //TODO 删除商品参数
        LambdaQueryWrapper<ProductAttribute> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ProductAttribute::getProductId,id);
        List<ProductAttribute> productAttributeList = productAttributeMapper.selectList(wrapper);
        //商品参数列表不为空
        if (CollectionUtils.isNotEmpty(productAttributeList)){
            List<String> idList = productAttributeList.stream().map(ProductAttribute::getId).collect(Collectors.toList());
            productAttributeMapper.deleteBatchIds(idList);
        }
        //TODO 删除商品图片
        LambdaQueryWrapper<ProductPic> wrapper1 = Wrappers.lambdaQuery();
        wrapper1.eq(ProductPic::getProductId,id);
        List<ProductPic> productPics = productPicMapper.selectList(wrapper1);
        //商品图片不为空
        if (CollectionUtils.isNotEmpty(productPics)){
            List<String> picIdList = productPics.stream().map(ProductPic::getId).collect(Collectors.toList());
            productPicMapper.deleteBatchIds(picIdList);
        }
        //TODO 删除商品审核
        LambdaQueryWrapper<Verify> wrapper2 = Wrappers.lambdaQuery();
        wrapper2.eq(Verify::getProductId,id);
        List<Verify> verifies = verifyMappper.selectList(wrapper2);
        if (CollectionUtils.isNotEmpty(verifies)){
            List<String> verifyList = verifies.stream().map(Verify::getId).collect(Collectors.toList());
            verifyMappper.deleteBatchIds(verifyList);
        }
    }


    /**
     * @description: 发布状态
     * @param
     * @return
     */
    @Override
    public void publishById(String id, Integer publishStatus) {
        Product product = productMapper.selectById(id);
        //商品不存在
        CustomAssert.notTrue(com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isNotEmpty(product),ResultCodeEnum.PRODUCT_NOT_EXIST_ERROR.getMessage());
        product.setPublishStatus(publishStatus);
        productMapper.updateById(product);
    }


    /**
     * @description: 根据不同类型查询商品列表
     * @param type 类型 1热卖；2特价;3新品
     * @return
     */
    @Cacheable(value = "index", key = "#type")
    @Override
    public List<ProductRsp> getApiProductByQuery(Integer type) {
        List<ProductRsp> productRsps = null;
        if (DictionaryConstants.NUMBER_0.equals(type)){
            productRsps = productMapper.selectBySalesVolume();
        } else if (DictionaryConstants.NUMBER_1.equals(type)){
            productRsps = productMapper.getApiProductByPrice();
        } else {
            productRsps = productMapper.getApiProductByCreateTime();
        }
        return productRsps;
    }

    /**
     * @description: 首页查询商品详情
     * @param id 商品id
     * @return
     */
    @Override
    public ProductRsp getProductById(String id) {


        Product product = productMapper.selectById(id);
        product.setViewCount(product.getViewCount()+1);
        //更新浏览数量
        baseMapper.updateById(product);
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        wrapper.eq("p.id",id);
        IPage<Product> pageParam = new Page<>(1, 1);
        IPage<ProductRsp> rsp = productMapper.selectPageByProductQueryVo(pageParam, wrapper);
        List<ProductRsp> productRsps = rsp.getRecords();
        //将商品的分类列表按照分类层级升序排列
        productRsps.stream().map(productRsp -> productRsp.getCategoryList().stream().sorted(Comparator.comparing(CategoryRsp::getCategoryLevel)));
        //把审核状态成功的记录放在列表第一个
        productRsps.stream().map(productRsp -> productRsp.getVerifyList().stream().sorted(Comparator.comparing(VerifyRsp::getVerifyStatus)));

        //TODO 通过商品的用户id查询该用户下所有的商品评价信息用于展示
        ProductRsp productRsp = productRsps.get(DictionaryConstants.NUMBER_0);
        CommentQueryVo commentQueryVo = new CommentQueryVo();
        //根据用户id查询商品评论
        commentQueryVo.setUseId(productRsp.getUserId());
        com.gzsxy.esjy.service.base.util.Page<?> page = new com.gzsxy.esjy.service.base.util.Page<>();
        IPage<CommentRsp> pageVo = commentMapper.getPageVo(page, commentQueryVo);
        List<CommentRsp> commentRsps = pageVo.getRecords();
        //评价总数
        productRsp.setCommentNumber(pageVo.getTotal());
        productRsp.setCommentList(commentRsps);
        //差评数
        long count = commentRsps.stream().filter(obj -> 0 <= obj.getContentScore().intValue() && obj.getContentScore().intValue() <= 2).count();
        //中评数
        long count1 = commentRsps.stream().filter(obj -> 2 < obj.getContentScore().intValue() && obj.getContentScore().intValue() <= 3.5).count();
        //好评数
        long count2 = commentRsps.stream().filter(obj -> 3.5 < obj.getContentScore().intValue() && obj.getContentScore().intValue() <= 5).count();
        productRsp.setPraiseNumber(count2);
        productRsp.setMediumEvaluationNumber(count1);
        productRsp.setNegativeCommentNumber(count);
        return productRsp;
    }


    /**
     * @description: 根据查询对象查询指定商品
     * @param
     * @return
     */
    @Override
    public List<ProductRsp> getProductByType(ApiProductQueryVo apiProductQueryVo) {

//        LambdaQueryWrapper<Product> wrapper = Wrappers.lambdaQuery();
//
//        //根据学校获取商品列表
//        if (StringUtils.isNotEmpty(apiProductQueryVo.getSchool())){
//            wrapper.eq(Product::getSchool,apiProductQueryVo.getSchool());
//        }
//        //根据分类id获取
//        if (StringUtils.isNotEmpty(apiProductQueryVo.getCategoryId())){
//            wrapper.eq(Product::getCategoryId,apiProductQueryVo.getCategoryId());
//        }
//        //根据创建时间降序
//        if (StringUtils.isNotEmpty(apiProductQueryVo.getGmtCreateSort())){
//            wrapper.orderByDesc(Product::getCreateTime);
//        }
//        //浏览数据降序
//        if (StringUtils.isNotEmpty(apiProductQueryVo.getViewCount())){
//            wrapper.orderByDesc(Product::getViewCount);
//        }
//        //如果type默认或为1则是价格升序，否则降序
//        if (apiProductQueryVo.getType()==null || apiProductQueryVo.getType()==1){
//            wrapper.orderByAsc(Product::getPrice);
//        }else {
//            wrapper.orderByDesc(Product::getPrice);
//        }
//        List<Product> products = productMapper.selectList(wrapper);
        List<ProductRsp> list = productMapper.getProductQueryVo(apiProductQueryVo);
//        List<ProductRsp> list = JSON.parseArray(JSON.toJSONString(products), ProductRsp.class);
        return list;
    }


    /**
     * @description: 根据商品id查询商品(外部服务调用)
     * @param
     * @return
     */
    @Override
    public ProductRsp getProById(String id) {
        Product product = productMapper.selectById(id);
        if (ObjectUtils.isNotEmpty(product)){
            ProductRsp productRsp = JSON.parseObject(JSON.toJSONString(product), ProductRsp.class);
            return productRsp;
        }
        return null;
        //这种方式如果product有null值字典会报异常
//        ProductRsp productRsp = new ProductRsp();
//        BeanUtils.copyProperties(product,productRsp);

    }


    /**
     * @description: 更新商品库存 (外部服务调用)
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void editNumber(String id, Integer number) {
        Product product = productMapper.selectById(id);
        //商品不存在
        CustomAssert.notTrue(com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isNotEmpty(product),ResultCodeEnum.PRODUCT_NOT_EXIST_ERROR.getMessage());
        //锁住同一个商品修改库存
        synchronized (id.intern()){
            product.setNumber(number);
            productMapper.updateById(product);
        }
    }
}
